紀錄Process Context Switch次數和idle time
在linux/sched.h中的struct task_struct的最後(”#endif”之後,”};”之前)加入
linux/sched.h 12unsigned int cs_count;struct timeval time_value;
如果將該變數加到task_struct中的任意位置,會產生問題,因為context switch是靠固定的位移記憶體大小來得到task_struct其中的變數,交換process的。在linux/sched.h中加入
linux/sched.h 12345struct process_switch_info{unsigned int counter_cpu, counter_IO;struct timeval time_cpu, time_IO;};
為了讓之後的systemcall-get_process_switch_info(struct process_switch_info *, int, int)可以傳入struct process_switch_info的變數在kernel/fork.c中return p之前加入
kernel/fork.c 123p->cs_count=0;p->time_value.tv_sec=0;p->time_value.tv_usec=0;
將其值初始化在kernel/sched/core.c中 context_switch(rq,prev,next)前後加上
kernel/sched/core.c 12345678struct timeval now_value,future_value;next->cs_count++;do_gettimeofday(&now_value);context_switch(rq, prev, next); /* unlocks the rq */do_gettimeofday(&future_value);prev->time_value.tv_sec+=future_value.tv_sec-now_value.tv_sec;prev->time_value.tv_usec+=future_value.tv_usec-now_value.tv_usec;prev->cs_count++;
在context switch之前 next的計數器+1,因為要準備switch過去next了;在context switch之後prev的計數器+1,因為已經switch回來了;另外加入now_value和future_value來記錄context switch前和後的時間,這樣就可以知道context switch其中的idle time了記得在include/linux/syscall.h裡面#include
因為system call裡面會用到在sched.h宣告的struct process_switch_info
如果在其他地方宣告struct process_switch_info,即要換成include那個在arch/x86/kernel新增gpsi.c,system call - get_process_switch_info如下
arch/x86/kernel/gpsi.c 123456789101112131415161718192021222324252627282930313233343536373839404142#include <linux/linkage.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/mm_types.h>#include <linux/fs.h>#include <linux/mm.h>#include <linux/time.h>asmlinkage void get_process_switch_info(struct process_switch_info * psi, int pid1, int pid2){struct process_switch_info* info;info=psi;struct task_struct *task_list;struct task_struct *process1;struct task_struct *process2;for_each_process(task_list){if(task_list->pid==pid1){process1=task_list;}else if(task_list->pid==pid2){process2=task_list;}}if(process1&&process2){info->counter_cpu =process1->cs_count;info->counter_IO =process2->cs_count;info->time_cpu.tv_sec =process1->time_value.tv_sec;info->time_cpu.tv_usec =process1->time_value.tv_usec;info->time_IO.tv_sec =process2->time_value.tv_sec;info->time_IO.tv_usec =process2->time_value.tv_usec;}else{printk("\nprocess1(PID:%d) or process2(PID:%d) not found\n",pid1,pid2);return 0;}return 0;}make modules_install
- make install
- 編譯test_process_switch.c並執行
會發現可以輸出context switch的次數了,和idle time了 - 最後要知道 限制3分鐘之內 context switch的次數和idle time,將core.c改成
kernel/sched/core.c 12345678910111213141516struct timeval now_value,future_value;if((next->start_time+180000000000)>ktime_get_ns()){next->cs_count++;}do_gettimeofday(&now_value);context_switch(rq, prev, next); /* unlocks the rq */do_gettimeofday(&future_value);if((prev->start_time+180000000000)>ktime_get_ns()){prev->time_value.tv_sec+=future_value.tv_sec-now_value.tv_sec;prev->time_value.tv_usec+=future_value.tv_usec-now_value.tv_usec;prev->cs_count++;}
在count和idle time外圍增加時間限制,當start_time超過三分鐘,即不count,也不增加idle time
ktime_get_ns()為得到目前cpu的時間,單位為ns,task_struct->start_time的單位也是ns,所以要以同一單位來度量,3分鐘即為180000000000ns
ktime_get_ns()和getnstimeofday()有什麼區別1234567891011121314151617ktime_t ktime_get(void){struct timekeeper *tk = &tk_core.timekeeper;unsigned int seq;ktime_t base;s64 nsecs;WARN_ON(timekeeping_suspended);do {seq = read_seqcount_begin(&tk_core.seq);base = tk->tkr.base_mono;nsecs = timekeeping_get_ns(&tk->tkr);} while (read_seqcount_retry(&tk_core.seq, seq));return ktime_add_ns(base, nsecs);}
兩個差別最大應該在於
base = tk->tkr.base_mono;
和
ts->tv_sec = tk->xtime_sec;
看看這兩者差在哪
tk->tkr.base_mono比tk->xtime_sec多了
tk->xtime_sec =>tk->xtime_sec
tk->tkr.base_mono =>(s64)(tk->xtime_sec + tk->wall_to_monotonic.tv_sec)*NSEC_PER_SEC+wall_to_monotonic.tv_nsec
多了wall_to_monotonic
我只要拿到xtime就好了,所以要用getnstimeofday64